<template>
  <s-modal
    :title="title"
    v-model:visible="visible"
    :width="properties.width"
    :confirm-loading="confirmLoading"
    :closable="!confirmLoading"
    @cancel="visible = false"
  >
    <template #footer>
      <a-button
        v-if="!disabled"
        key="back"
        @click="
          () => {
            if (!confirmLoading) {
              visible = false
            }
          }
        "
      >
        取消
      </a-button>
      <a-button
        v-if="!disabled"
        key="submit"
        type="primary"
        :loading="confirmLoading"
        @click="$save"
      >
        {{ okText }}
      </a-button>
    </template>
    <div :style="{ height: properties.height }">
      <s-scroll>
        <s-form ref="form" :value="fakeValue">
          <slot name="header"></slot>
          <s-dynamic-form
            ref="dynamicForm"
            :form="fakeValue"
            :items="items"
            :disable-item="disabled"
            @change="$itemChange"
          >
            <template #item="{ properties, type }">
              <slot name="item" :properties="properties" :type="type"></slot>
            </template>
          </s-dynamic-form>
          <slot :form="fakeValue"></slot>
        </s-form>
      </s-scroll>
    </div>
  </s-modal>
</template>

<script>
export default {
  name: 'DynamicFormDialog',
  props: {
    disabled: {
      type: Boolean,
      required: false,
      default: false
    },
    width: {
      type: String,
      required: false,
      default: '800px'
    },
    title: {
      type: String,
      required: false,
      default: '详情'
    },
    okText: {
      type: String,
      required: false,
      default: '保存'
    },
    height: {
      type: String,
      required: false,
      default: '600px'
    },
    formId: {
      type: String,
      required: false
    },
    formItems: {
      type: Array,
      default: () => {
        return []
      }
    },
    modelValue: {
      type: Object
    },
    pullFormData: {
      type: Function,
      required: false
    }
  },
  emits: ['change', 'update:modelValue', 'save'],
  data() {
    return {
      fakeValue: this.modelValue || {},
      confirmLoading: false,
      visible: false,
      items: this.formItems,
      properties: {
        height: this.height,
        width: this.width
      }
    }
  },
  watch: {
    modelValue: {
      handler: function (val, oldVal) {
        this.fakeValue = val
      },
      deep: true
    },
    formItems: {
      handler: function (val, oldVal) {
        this.items = val
      },
      deep: true
    }
  },
  methods: {
    $save() {
      const form = this.$refs.form
      form.validate((values, fullValue) => {
        this.confirmLoading = true
        this.$emit('save', values, fullValue, this)
      })
    },
    $itemChange(val) {
      this.$emit('change', val)
      this.$emit('update:modelValue', this.fakeValue)
    },
    reset() {
      this.confirmLoading = false
    },
    resetFormValue() {
      this.fakeValue = {}
      this.$emit('update:modelValue', {})
    },
    init(callBack) {
      if (this.formId) {
        this.$loading(true)
        this.$loadDynamicForm(this.formId)
          .then((res) => {
            this.$loading(false)
            if (!res.data) {
              this.$message.warn('表单不存在')
            } else {
              this.properties.height = res.data.moduleForm.properties.height
              this.properties.width = res.data.moduleForm.properties.width
              this.items = res.data.moduleForm.data
              if (this.pullFormData) {
                this.$loading(true)
                this.pullFormData()
                  .then((val) => {
                    this.$loading(false)
                    if (!val.data) {
                      this.$message.warn('数据不存在')
                    } else {
                      this.fakeValue = val.data
                      this.$emit('update:modelValue', this.fakeValue)
                      this.open()
                    }
                  })
                  .catch((e) => {
                    this.$loading(false)
                  })
              } else {
                if (callBack) {
                  callBack(this)
                } else {
                  this.open()
                }
              }
            }
          })
          .catch(() => {
            this.$loading(false)
          })
      }
    },
    open() {
      this.visible = true
      this.confirmLoading = false
    },
    close() {
      this.visible = false
      this.confirmLoading = false
    }
  }
}
</script>

<style lang="less" scoped></style>
